package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	"openmanus/agent"
	"openmanus/config"
	"openmanus/flow"
	"openmanus/tool"
	"os"
	"strings"

	"github.com/axcom/ninego/class"
	logger "github.com/axcom/ninego/log"
)

func main() {

	cfgType := flag.String("l", "openai", "选用LLM大模型配置名称(定义在llm下)")
	cfgPath := flag.String("c", "config.json", "加载指定的config配置文件")
	cfgDebug := flag.String("d", "off", "日志文件记录 model: off(关闭)/info/warn/error/debug")
	cfgMode := flag.String("m", "manus", "运行模式: flow 或 manus(默认)")
	flag.Parse()

	switch *cfgDebug {
	case "debug":
		logger.SetLevel(logger.LevelDebug)
	case "info":
		logger.SetLevel(logger.LevelInfo)
	case "warn":
		logger.SetLevel(logger.LevelWarn)
	case "error":
		logger.SetLevel(logger.LevelError)
	case "panic":
		logger.SetLevel(logger.LevelPanic)
	default:
		logger.SetLevel(logger.LevelFatal)
	}
	logger.Println("加载配置文件:", *cfgPath)
	// 加载配置
	cfg, err := config.LoadConfig(*cfgPath)
	if err != nil {
		logger.Errorf("加载配置失败: %v", err)
		fmt.Println("无法加载配置，请确保配置文件正确设置。")
		os.Exit(1)
	}

	// 创建LLM客户端
	llmClient, err := agent.CreateLLM(cfg, *cfgType)
	if err != nil {
		logger.Error("创建LLM客户端失败: %v", err)
		fmt.Println("无法创建LLM客户端，请检查API配置。")
		os.Exit(1)
	}

	if *cfgMode == "manus" {
		runManus(cfg, llmClient)
	} else if *cfgMode == "flow" {
		runFlow(cfg, llmClient)
	} else {
		logger.Fatalf("不支持的运行模式: %s", *cfgMode)
	}
}

// runMCP 运行 MCP 服务
func runManus(cfg *config.Config, llmClient *agent.LLMClient) {
	// 先声明 agentInstance 变量（避免 defer 中引用未定义变量）
	var agentInstance *agent.Manus // 假设类型是 *agent.Manus，根据实际类型调整
	// 将清理资源的逻辑放在 defer 中，确保无论正常/异常退出都会执行
	defer func() {
		// 检查 agentInstance 是否初始化成功（避免空指针）
		if agentInstance != nil {
			if err := agentInstance.Cleanup(); err != nil {
				logger.Error("清理代理资源失败: %v", err)
			}
			agentInstance.Disconnect_mcp_server()
		}
	}()

	// 创建代理
	agentInstance = agent.NewManusAgent("Manus", llmClient, cfg.MCPSettings)
	class.Create(agentInstance)

	// 运行交互循环
	fmt.Println("欢迎使用 OpenManus-Go！输入 'exit' 退出程序。")
	scanner := bufio.NewScanner(os.Stdin)

	for {
		fmt.Print("\n你: ")
		scanner.Scan()
		userInput := scanner.Text()

		if strings.ToLower(userInput) == "exit" {
			fmt.Println("再见！")
			break
		}
		if strings.ToLower(userInput) == "tool" {
			toolList := agentInstance.AvailableTools.GetTools()
			for _, t := range toolList {
				fmt.Printf("- %s: %s\n", t.Name(), t.Description())
			}
			continue
		}
		if strings.ToLower(userInput) == "mcp" {
			for k, _ := range agentInstance.MCPClients {
				fmt.Println(" -", k)
			}
			continue
		}

		// 运行代理
		fmt.Print("\nOpenManus: ")
		result, err := agentInstance.Run(context.Background(), userInput)
		if err != nil {
			logger.Error("代理运行失败: %v", err)
			fmt.Printf("发生错误: %v\n", err)
		} else {
			fmt.Println("Result:", result)
		}
	}
}

func runFlow(cfg *config.Config, llmClient *agent.LLMClient) {
	// 创建工具集合
	tools := tool.NewToolCollection()
	//tool.RegisterDefaultTools()

	// 创建智能体
	manus := class.Create(agent.NewManusAgent("manus", llmClient, cfg.MCPSettings))
	manus.Description = ` - 擅长使用工具解决复杂问题
 - 适合需要多工具协作的任务
 - 可以处理文件操作、代码生成等任务
 - 适合需要精确执行的任务
`
	react := class.Create(agent.NewToolCallAgent("react", llmClient))
	react.Description = ` - 采用"思考-行动-观察"循环
 - 适合需要多步骤推理的任务
 - 可以处理需要反复尝试的任务
 - 适合需要探索性解决的任务
`
	agents := map[string]agent.IBaseAgent{
		"manus": manus,
		"react": react,
	}

	// 运行交互循环
	fmt.Println("欢迎使用 OpenManus-Go(Flow)！输入 'exit' 退出程序。")
	scanner := bufio.NewScanner(os.Stdin)

	for {
		fmt.Print("\n你: ")
		scanner.Scan()
		userInput := scanner.Text()

		if strings.ToLower(userInput) == "exit" {
			fmt.Println("再见！")
			break
		}

		// 运行代理
		fmt.Print("\nFlow: ")
		// 执行任务
		if err := executeTask(agents, tools, llmClient, userInput); err != nil {
			logger.Errorf("执行任务失败: %v", err)
			fmt.Printf("发生错误: %v\n", err)
		}
	}

}

func executeTask(agents map[string]agent.IBaseAgent, tools *tool.ToolCollection, llmClient *agent.LLMClient, task string) error {
	fmt.Println("run...")

	// 创建任务流
	factory := flow.NewDefaultFlowFactory()
	taskFlow, err := factory.CreateFlow(agents, tools, llmClient)
	if err != nil {
		return err
	}

	// 执行任务流
	result, err := taskFlow.Execute(context.Background(), task)
	if err != nil {
		return err
	}

	fmt.Printf("任务执行完成: %s\n", result)
	return nil
}
